// ----------------------------------------------------------------------------
// hlsl_intrinsic.scalar.h
// ----------------------------------------------------------------------------
/*
 Description: 組み込み関数のデバッグ用参照実装. 
 */
#ifndef FW_BASE_HLSL_INTRINSIC_SCALAR_H
#define FW_BASE_HLSL_INTRINSIC_SCALAR_H
#include <math.h>

namespace fw
{
	FW_FORCE_INLINE vec3 _impl_acos(avec3 x)
	{
		vec3 y;
		y.setX(acosf(x.getX()));
		y.setY(acosf(x.getY()));
		y.setZ(acosf(x.getZ()));
		return y;
	}
	
	FW_FORCE_INLINE vec4 _impl_acos(avec4 x)
	{
		vec4 y;
		y.setX(acosf(x.getX()));
		y.setY(acosf(x.getY()));
		y.setZ(acosf(x.getZ()));
		y.setW(acosf(x.getW()));
		return y;
	}

	FW_FORCE_INLINE vec3 _impl_asin(avec3 x)
	{
		vec3 y;
		y.setX(asinf(x.getX()));
		y.setY(asinf(x.getY()));
		y.setZ(asinf(x.getZ()));
		return y;
	}
	
	FW_FORCE_INLINE vec4 _impl_asin(avec4 x)
	{
		vec4 y;
		y.setX(asinf(x.getX()));
		y.setY(asinf(x.getY()));
		y.setZ(asinf(x.getZ()));
		y.setW(asinf(x.getW()));
		return y;
	}

	FW_FORCE_INLINE vec3 _impl_atan(avec3 x)
	{
		vec3 y;
		y.setX(atan(x.getX()));
		y.setY(atan(x.getY()));
		y.setZ(atan(x.getZ()));
		return y;
	}
	
	FW_FORCE_INLINE vec4 _impl_atan(avec4 x)
	{
		vec4 y;
		y.setX(atan(x.getX()));
		y.setY(atan(x.getY()));
		y.setZ(atan(x.getZ()));
		y.setW(atan(x.getW()));
		return y;
	}

	FW_FORCE_INLINE vec3 _impl_ceil(avec3 x)
	{
		vec3 y;
		y.setX(ceil(x.getX()));
		y.setY(ceil(x.getY()));
		y.setZ(ceil(x.getZ()));
		return y;
	}
	
	FW_FORCE_INLINE vec4 _impl_ceil(avec4 x)
	{
		vec4 y;
		y.setX(ceil(x.getX()));
		y.setY(ceil(x.getY()));
		y.setZ(ceil(x.getZ()));
		y.setW(ceil(x.getW()));
		return y;
	}

	FW_FORCE_INLINE vec3 _impl_cos(avec3 x)
	{
		vec3 y;
		y.setX(cosf(x.getX()));
		y.setY(cosf(x.getY()));
		y.setZ(cosf(x.getZ()));
		return y;
	}
	
	FW_FORCE_INLINE vec4 _impl_cos(avec4 x)
	{
		vec4 y;
		y.setX(cosf(x.getX()));
		y.setY(cosf(x.getY()));
		y.setZ(cosf(x.getZ()));
		y.setW(cosf(x.getW()));
		return y;
	}

	FW_FORCE_INLINE vec3 _impl_floor(avec3 x)
	{
		vec3 y;
		y.setX(floorf(x.getX()));
		y.setY(floorf(x.getY()));
		y.setZ(floorf(x.getZ()));
		return y;
	}
	
	FW_FORCE_INLINE vec4 _impl_floor(avec4 x)
	{
		vec4 y;
		y.setX(floorf(x.getX()));
		y.setY(floorf(x.getY()));
		y.setZ(floorf(x.getZ()));
		y.setW(floorf(x.getW()));
		return y;
	}

	FW_FORCE_INLINE vec3 _impl_frac(avec3 x)
	{
		vec3 y;
		y.setX(x.getX() - static_cast<float>(static_cast<int>(x.getX())));
		y.setY(x.getY() - static_cast<float>(static_cast<int>(x.getY())));
		y.setZ(x.getZ() - static_cast<float>(static_cast<int>(x.getZ())));
		return y;
	}
	
	FW_FORCE_INLINE vec4 _impl_frac(avec4 x)
	{
		vec4 y;
		y.setX(x.getX() - static_cast<float>(static_cast<int>(x.getX())));
		y.setY(x.getY() - static_cast<float>(static_cast<int>(x.getY())));
		y.setZ(x.getZ() - static_cast<float>(static_cast<int>(x.getZ())));
		y.setW(x.getW() - static_cast<float>(static_cast<int>(x.getW())));
		return y;
	}

	FW_FORCE_INLINE vec3 _impl_log2(avec3 x)
	{
		static const float divLn10_2 = 1.0f/log10f(2.0f);
		vec3 y;
		y.setX(log10f(x.getX()));
		y.setY(log10f(x.getY()));
		y.setZ(log10f(x.getZ()));
		return y * divLn10_2;
	}
	
	FW_FORCE_INLINE vec4 _impl_log2(avec4 x)
	{
		static const float divLn10_2 = 1.0f/log10f(2.0f);
		vec4 y;
		y.setX(log10f(x.getX()));
		y.setY(log10f(x.getY()));
		y.setZ(log10f(x.getZ()));
		y.setW(log10f(x.getW()));
		return y * divLn10_2;
	}
	
	FW_FORCE_INLINE vec3 _impl_log10(avec3 x)
	{
		vec3 y;
		y.setX(log10f(x.getX()));
		y.setY(log10f(x.getY()));
		y.setZ(log10f(x.getZ()));
		return y;
	}
	
	FW_FORCE_INLINE vec4 _impl_log10(avec4 x)
	{
		vec4 y;
		y.setX(log10f(x.getX()));
		y.setY(log10f(x.getY()));
		y.setZ(log10f(x.getZ()));
		y.setW(log10f(x.getW()));
		return y;
	}
	
	FW_FORCE_INLINE vec3 _impl_pow(avec3 x, avec3 y)
	{
		vec3 z;
		z.setX(powf(x.getX(), y.getX()));
		z.setY(powf(x.getY(), y.getY()));
		z.setZ(powf(x.getZ(), y.getZ()));
		return z;
	}
	
	FW_FORCE_INLINE vec4 _impl_pow(avec4 x, avec4 y)
	{
		vec4 z;
		z.setX(powf(x.getX(), y.getX()));
		z.setY(powf(x.getY(), y.getY()));
		z.setZ(powf(x.getZ(), y.getZ()));
		z.setW(powf(x.getW(), y.getW()));
		return z;
	}
	
	FW_FORCE_INLINE vec3 _impl_sqrt(avec3 x)
	{
		vec3 y;
		y.setX(sqrtf(x.getX()));
		y.setY(sqrtf(x.getY()));
		y.setZ(sqrtf(x.getZ()));
		return y;
	}
	
	FW_FORCE_INLINE vec4 _impl_sqrt(avec4 x)
	{
		vec4 y;
		y.setX(sqrtf(x.getX()));
		y.setY(sqrtf(x.getY()));
		y.setZ(sqrtf(x.getZ()));
		y.setW(sqrtf(x.getW()));
		return y;
	}

	FW_FORCE_INLINE vec3 _impl_rsqrt(avec3 x)
	{
		vec3 y;
		y.setX(1.0f/sqrtf(x.getX()));
		y.setY(1.0f/sqrtf(x.getY()));
		y.setZ(1.0f/sqrtf(x.getZ()));
		return y;
	}
	
	FW_FORCE_INLINE vec4 _impl_rsqrt(avec4 x)
	{
		vec4 y;
		y.setX(1.0f/sqrtf(x.getX()));
		y.setY(1.0f/sqrtf(x.getY()));
		y.setZ(1.0f/sqrtf(x.getZ()));
		y.setW(1.0f/sqrtf(x.getW()));
		return y;
	}
	
	FW_FORCE_INLINE vec3 _impl_sin(avec3 x)
	{
		vec3 y;
		y.setX(sinf(x.getX()));
		y.setY(sinf(x.getY()));
		y.setZ(sinf(x.getZ()));
		return y;
	}
	
	FW_FORCE_INLINE vec4 _impl_sin(avec4 x)
	{
		vec4 y;
		y.setX(sinf(x.getX()));
		y.setY(sinf(x.getY()));
		y.setZ(sinf(x.getZ()));
		y.setW(sinf(x.getW()));
		return y;
	}

	FW_FORCE_INLINE void _impl_sincos(avec3 x, vec3& s, vec3& c)
	{
		s = _impl_sin(x);
		c = _impl_cos(x);
	}
	
	FW_FORCE_INLINE void _impl_sincos(avec4 x, vec4& s, vec4& c)
	{
		s = _impl_sin(x);
		c = _impl_cos(x);
	}
	
} // namespace fw

#endif // FW_BASE_HLSL_INTRINSIC_SCALAR_H
